# A Vector is a list of words in which each word is represented
# by the index associated with it in the dictionary.

class Vector
  attr_reader :num_words, :max_word_index, :min_word_index
  
  def initialize
    @frequencies = []
    @num_words = 0
    @max_word_index = 0
    @min_word_index = Float::MAX
  end
  
  def [](index)
    retValue = @frequencies[index]
    retValue = 0 if @frequencies[index].nil?
    retValue
  end
  
  def add_word_index(index)
    @max_word_index = index if @max_word_index < index
    @min_word_index = index if @min_word_index > index
    
    if @frequencies[index].nil?
      @frequencies[index] = 0
      @num_words += 1
    end 
    
    @frequencies[index] += 1
  end
  
  # computes the cosine distance between two vectors
  # distance(a,b) = (a.b) / (||a|| * ||b||)
  def distance(vector)
    self.dot(vector) / (self.length() * vector.length)
  end
  
  # computes the dot product of two vectors
  # a . b =  a[1] * b[1] + a[2] * b[2] + ... + a[n] * b[n] 
  def dot(vector)
    dot = 0
    max_index = [@max_word_index, vector.max_word_index].min
    min_index = [@min_word_index, vector.min_word_index].max
    
    min_index.upto(max_index) { |i| dot += self[i] * vector[i] }
    
    dot
  end
  
  # computes the length of this vector
  # length_of(a) = sqrt(a[1]^2 + a[2]^2 + ... + a[n]^2)
  def length
    Math.sqrt(@frequencies.compact.inject(0) { |l, e| l + (e * e) })
  end
  
end
